<template>
    <div class="study-screen" :style="{ backgroundImage: `url(${bgUrl})` }">
        <div class="blur-overlay"></div>

        <header class="topbar">
            <div class="topbar-left">
            <button class="icon-btn back-btn" aria-label="back" @click="backToHome">
                <svg viewBox="0 0 24 24" width="24" height="24">
                    <path fill="currentColor" d="M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
                </svg>
            </button>
            <div class="progress-label">{{ progressLabel }}</div>
            </div>
            <div class="top-actions">
                <button class="icon-btn" aria-label="favorite" @click="noop">
                    <svg viewBox="0 0 24 24" width="22" height="22">
                        <path fill="currentColor" d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.46 4.73L5.82 21z"/>
                    </svg>
                </button>
            </div>
        </header>

        <main class="study-body">
            <section class="study-content" v-if="wordList.length > 0">
                <div class="word-section-wrapper">
                <div class="word-section">
                        <div class="word-header">
                            <div class="word-content">
                                <h1 class="word-text">{{ currentWord.word || '' }}</h1>
                    <div class="word-meta">
                        <button class="chip" @click="playAudio" :disabled="!currentWord.audioUrl">
                            英 🔊
                        </button>
                        <span class="phonetic">{{ currentWord.phonetic || '' }}</span>
                    </div>
                                <p class="word-hint" v-if="!showWordDetail && currentLearnRound === 1">先回想词义再选择，想不起来「看答案」</p>
                            </div>
                            <!-- 学习进度圆圈（竖向，从下而上点亮） -->
                            <div class="learn-progress-circles">
                                <div
                                    v-for="round in 3"
                                    :key="round"
                                    class="progress-circle"
                                    :class="{ active: getLearnProgress(currentWord.wordId) >= round }"
                                ></div>
                            </div>
                        </div>
                    <div v-if="showWordDetail" class="word-meanings-inline">
                        <div
                            v-for="(meaningItem, meaningIndex) in parsedMeanings"
                            :key="meaningIndex"
                            class="meaning-item-inline"
                        >
                            <span class="part-of-speech-inline">{{ meaningItem.partOfSpeech }}</span>
                            <span class="meaning-text-inline">{{ meaningItem.meaning }}</span>
                        </div>
                        <div class="example-box-inline" v-if="currentWord.exampleSentenceEn || currentWord.exampleSentenceCn">
                            <div class="example-icon-inline">💬</div>
                            <div class="example-content-inline">
                                <div class="example-en-inline" v-if="currentWord.exampleSentenceEn">{{ currentWord.exampleSentenceEn }}</div>
                                <div class="example-cn-inline" v-if="currentWord.exampleSentenceCn">{{ currentWord.exampleSentenceCn }}</div>
                            </div>
                        </div>
                    </div>
                    </div>
                </div>

                <!-- 第二、三遍学习时的按钮（复习模式） -->
                <!-- 只在第二、三遍学习时显示，且不在显示单词详情时显示 -->
                <transition name="fade-choices">
                    <div v-if="currentLearnRound > 1 && !showWordDetail && !hasAnswered && !hadForgetAnswer && !hadKnowAnswer" class="choices">
                        <button class="btn know" @click="handleLearnAnswer('know')">认识</button>
                        <button class="btn forget" @click="handleLearnAnswer('forget')">不认识</button>
                    </div>
                </transition>

                <!-- 圆圈独立于容器，不受 fade-options 动画影响 -->
                <div class="circle-selectors left" :style="circleTopPosition !== null ? { top: circleTopPosition + 'px' } : {}" v-if="isCirclePositionReady && !hideOptions && (currentLearnRound === 1 || hadCorrectAnswer)">
                                <div
                                    v-for="(option, index) in parsedOptions"
                                    :key="'left-circle-' + index"
                                    class="circle-wrapper"
                        :style="{ height: getOptionHeight(index) + 'px' }"
                                    @click="selectOption(index)"
                                >
                                    <div
                                        class="circle-selector"
                                        :class="circleClass(index)"
                                    >
                            <div class="circle"></div>
                                        </div>
                            </div>
                        </div>

                <transition :name="optionsAlreadyShown ? '' : 'fade-options'" @after-enter="optionsAlreadyShown = true">
                    <div v-if="!hideOptions && (currentLearnRound === 1 || hadCorrectAnswer)" :key="`options-${currentWord?.wordId || ''}`" class="options-container" :class="{ 'no-transition': hadCorrectAnswer }">
                        <div class="options-wrapper">
                        <div class="options-list">
                            <div
                                v-for="(option, index) in parsedOptions"
                                :key="option.id || index"
                                class="option-row"
                            >
                                <div
                                    class="option-item"
                                    :class="optionClass(index)"
                                    role="button"
                                    tabindex="0"
                                    @click="selectOption(index)"
                                >
                                    <div class="option-content">
                                        <div class="option-header">
                                            <span class="option-label">{{ option.partOfSpeech || '释义' }}</span>
                                            <transition name="fade-word">
                                                <span class="option-word" v-if="shouldShowWord(index)">
                                                        {{ getOptionWord(option, index) }}
                                                </span>
                                            </transition>
                                        </div>
                                            <div class="option-text">
                                                {{ option.meaning }}
                                            </div>
                                    </div>
                                    <div class="selected-line" v-if="selectedIndices.includes(index)"></div>
                                </div>
                            </div>
                        </div>
                        </div>
                    </div>
                </transition>

                <!-- 圆圈独立于容器，不受 fade-options 动画影响 -->
                <div class="circle-selectors right" :style="circleTopPosition !== null ? { top: circleTopPosition + 'px' } : {}" v-if="isCirclePositionReady && !hideOptions && (currentLearnRound === 1 || hadCorrectAnswer)">
                                <div
                                    v-for="(option, index) in parsedOptions"
                                    :key="'right-circle-' + index"
                                    class="circle-wrapper"
                        :style="{ height: getOptionHeight(index) + 'px' }"
                                    @click="selectOption(index)"
                                >
                                    <div
                                        class="circle-selector"
                                        :class="circleClass(index)"
                                    >
                            <div class="circle"></div>
                                        </div>
                                    </div>
                                </div>

                <div class="action-bar">
                    <button
                        v-if="showViewAnswerButton"
                        class="action-btn ghost"
                        @click="viewAnswer"
                    >
                        看答案
                    </button>
                    <button
                        v-if="showContinueButton"
                        class="action-btn next-word-btn"
                        @click="continueToDetail"
                    >
                        继续
                    </button>
                    <button
                        v-if="showNextButton"
                        class="action-btn next-word-btn"
                        @click="nextWord"
                    >
                        下一词
                    </button>
                </div>

                <transition name="detail-fade">
                    <div class="word-detail-section" v-if="showWordDetail && derivativeList.length > 0">
                        <div class="derivative-words">
                            <div class="derivative-title">衍生词</div>
                            <div class="derivative-list">
                                <span
                                    v-for="(item, idx) in derivativeList"
                                    :key="idx"
                                    class="derivative-item"
                                >
                                    {{ item }}
                                </span>
                            </div>
                        </div>
                    </div>
                </transition>
            </section>
        </main>
    </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { bgUrl } from '@/config/background.js'
import { fetchLearnWords, updateLearnRecord, saveStudySession } from '@/utils/api.js'

const router = useRouter()

const wordList = ref([])
const currentIndex = ref(0)
const isLoading = ref(false)

const selectedIndices = ref([])
const hasAnswered = ref(false)
const hideOptions = ref(false)
const showWordDetail = ref(false)
const showCorrectAnswer = ref(false)
const isViewAnswerMode = ref(false)
const hadWrongAttempt = ref(false)
const hadCorrectAnswer = ref(false) // 标记是否已选择正确答案，等待用户点击"继续"（第一遍）
const hadForgetAnswer = ref(false) // 标记是否已选择"不认识"，等待用户点击"继续"（第二、三遍）
const hadKnowAnswer = ref(false) // 标记是否已选择"认识"，等待用户点击"继续"（第二、三遍）
const optionsAlreadyShown = ref(false) // 标记选项框是否已经显示过，用于禁用进入动画

let audio = null
let timers = []
let studyStartTime = null // 学习开始时间

// 学习遍数管理：每个单词的学习遍数 { wordId: round }
// round 表示当前单词已经学完了几遍（1, 2, 3）
const learnProgress = ref({})
// 待复习队列：点击"不认识"的单词，会在下一个单词的第二或第三遍后重新学习
const reviewQueue = ref([])
// 当前单词的当前学习遍数
const currentLearnRound = computed(() => {
    const wordId = currentWord.value?.wordId
    if (!wordId) return 1
    const completedRounds = learnProgress.value[wordId] || 0
    // 如果 completedRounds 为 0，说明是第1遍学习
    // 如果 completedRounds 为 1，说明是第2遍学习
    // 如果 completedRounds 为 2，说明是第3遍学习
    const round = completedRounds + 1
    console.log('[currentLearnRound] wordId:', wordId, '已完成:', completedRounds, '当前遍:', round)
    return round
})

const currentWord = computed(() => wordList.value[currentIndex.value] || {})
const totalWords = computed(() => wordList.value.length)
const progressLabel = computed(() => {
    const total = totalWords.value || 0
    const current = total > 0 ? currentIndex.value + 1 : 0
    return `${current}/${total}`
})
const progressDots = computed(() => {
    const total = totalWords.value || 0
    const baseLength = total > 0 ? total : 10
    const length = Math.max(baseLength, 4)
    return Array.from({ length }, (_, index) => index)
})

const parsedOptions = computed(() => {
    const options = currentWord.value?.options || []
    return options.map((option, index) => {
        const originalText = option.text ?? option.meaning ?? ''
        const partMatches = [...originalText.matchAll(/([a-z]+\.)/gi)]
        let partOfSpeech = ''
        let meaning = originalText

        if (partMatches.length > 0) {
            partOfSpeech = partMatches[0][1] || partMatches[0][0]
            const start = partMatches[0].index + (partMatches[0][0]?.length || 0)
            const end = partMatches.length > 1 ? partMatches[1].index : originalText.length
            meaning = originalText.slice(start, end).trim()
        }

        meaning = meaning.replace(/\s+/g, ' ').trim()

        return {
            ...option,
            order: index,
            originalText,
            partOfSpeech: partOfSpeech || option.partOfSpeech || '',
            meaning: meaning || originalText,
            // 直接使用后端返回的 word 字段
            word: option.word || '',
        }
    })
})

const correctOptionIndex = computed(() => {
    if (!parsedOptions.value.length) return -1
    const correctMeaning = currentWord.value?.correctMeaning
    if (correctMeaning) {
        const idx = parsedOptions.value.findIndex(option => option.originalText === correctMeaning)
        if (idx !== -1) {
            return idx
        }
    }
    return 0
})

const parsedMeanings = computed(() => {
    const meaningText = currentWord.value?.correctMeaning
    if (!meaningText) return []

    const partMatches = [...meaningText.matchAll(/([a-z]+\.)/gi)]
    const list = []

    if (partMatches.length === 0) {
        list.push({
            partOfSpeech: currentWord.value?.partOfSpeech || '',
            meaning: meaningText.trim(),
        })
    } else {
        for (let i = 0; i < partMatches.length; i += 1) {
            const match = partMatches[i]
            const part = match[1] || match[0]
            const start = match.index + match[0].length
            const end = i < partMatches.length - 1 ? partMatches[i + 1].index : meaningText.length
            const segment = meaningText.slice(start, end).replace(/\s+/g, ' ').trim()
            if (segment) {
                list.push({
                    partOfSpeech: part,
                    meaning: segment,
                })
            }
        }
    }

    return list
})

const derivativeList = computed(() => {
    if (Array.isArray(currentWord.value?.derivatives)) {
        return currentWord.value.derivatives
    }

    if (typeof currentWord.value?.derivatives === 'string') {
        return currentWord.value.derivatives
            .split(/[;,；，]/)
            .map(item => item.trim())
            .filter(Boolean)
    }

    return []
})

const hasSelectedAny = computed(() => selectedIndices.value.length > 0 || hasAnswered.value)
const hasWrongAnswer = computed(() => selectedIndices.value.some(index => index !== correctOptionIndex.value))

const showViewAnswerButton = computed(() =>
    currentLearnRound.value === 1 &&
    !showWordDetail.value &&
    !hasSelectedAny.value &&
    parsedOptions.value.length > 0
)

const showContinueButton = computed(() => {
    // 第一遍学习：答对或答错后显示"继续"按钮
    if (currentLearnRound.value === 1) {
        return (hadWrongAttempt.value || hadCorrectAnswer.value) && !showWordDetail.value
    }
    // 第二、三遍学习：只有选择"不认识"后显示"继续"按钮，选择"认识"后直接显示单词意思
    if (currentLearnRound.value > 1) {
        return hadForgetAnswer.value && !showWordDetail.value
    }
    return false
})

const showNextButton = computed(() => {
    // 显示"下一词"按钮的条件：
    // 1. 显示了单词详情
    // 2. 有单词列表
    // 3. 如果是第一遍学习，需要已经完成（hasAnswered）
    // 4. 如果是第二、三遍学习，需要已经完成（hasAnswered）
    if (!showWordDetail.value || totalWords.value === 0) return false
    
    const wordId = currentWord.value?.wordId
    if (!wordId) return false
    
    const completedRounds = learnProgress.value[wordId] || 0
    
    // 如果已完成3遍，显示"下一词"按钮
    if (completedRounds >= 3) {
        return true
    }
    
    // 如果还没完成3遍，也显示"下一词"按钮（点击后会进入下一遍）
    return hasAnswered.value
})

function dotClass(index) {
    const position = index + 1
    const currentPosition = Math.min(currentIndex.value + 1, progressDots.value.length)
    return {
        completed: position < currentPosition,
        current: position === currentPosition,
    }
}

function scheduleTask(task, delay) {
    const timer = setTimeout(() => {
        task()
        timers = timers.filter(id => id !== timer)
    }, delay)
    timers.push(timer)
}

function clearTimers() {
    timers.forEach(id => clearTimeout(id))
    timers = []
}

function resetState() {
    clearTimers()
    selectedIndices.value = []
    hasAnswered.value = false
    hideOptions.value = false
    showWordDetail.value = false
    showCorrectAnswer.value = false
    isViewAnswerMode.value = false
    hadWrongAttempt.value = false
    // 重置选项框显示标志
    optionsAlreadyShown.value = false
    // 重置圆圈位置，准备下一遍学习
    isCirclePositionReady.value = false
    circleTopPosition.value = null
    // 等待DOM更新后再计算位置
    // 切换单词时需要强制隐藏，重新计算位置
    nextTick(() => {
        nextTick(() => {
            updateOptionHeights(true)
        })
    })
}

// 获取单词已完成的遍数（用于显示进度圆圈）
function getLearnProgress(wordId) {
    if (!wordId) return 0
    const progress = learnProgress.value[wordId] || 0
    console.log('[getLearnProgress] wordId:', wordId, '进度:', progress)
    return progress
}

// 处理学习答案（第二、三遍）
async function handleLearnAnswer(confidence) {
    // 防止重复点击
    if (!currentWord.value?.wordId) return
    if (hasAnswered.value) return
    
    const wordId = currentWord.value.wordId
    const currentRound = currentLearnRound.value
    
    // 标记已回答
    hasAnswered.value = true
    
    // 如果选择"不认识"
    if (confidence === 'forget') {
        // 学习遍数清零
        learnProgress.value[wordId] = 0
        console.log('第', currentRound, '遍学习选择"不认识"，学习遍数清零，wordId:', wordId)
        
        // 将单词加入待复习队列（如果还没有加入，避免重复）
        const alreadyInQueue = reviewQueue.value.find(item => item.wordId === wordId)
        if (!alreadyInQueue) {
            reviewQueue.value.push({
                wordId,
                word: currentWord.value.word,
                insertAfterRound: currentRound === 2 ? 2 : 3, // 在第2遍后插入，或第3遍后插入
            })
            console.log('单词加入待复习队列:', reviewQueue.value)
        } else {
            console.log('单词已在待复习队列中，跳过重复添加，wordId:', wordId)
        }
        
        // 尝试提交到后端
        try {
            await updateLearnRecord(wordId, confidence)
            console.log(`第${currentRound}遍学习记录提交成功:`, confidence)
        } catch (error) {
            console.error('提交学习记录失败（但不影响学习进度）:', error)
        }
        
        // 设置标记，表示已选择"不认识"，等待用户点击"继续"
        hadForgetAnswer.value = true
        
        // 不自动跳转，等待用户点击"继续"按钮
        return
    }
    
    // 选择"认识"：完成这一遍
    // 先更新学习进度（即使 API 失败也要更新，保证 UI 正常）
    learnProgress.value[wordId] = currentRound
    console.log('第', currentRound, '遍学习完成（认识），wordId:', wordId, '当前进度:', learnProgress.value[wordId])
    
    // 然后尝试提交到后端（失败不影响 UI）
    try {
        await updateLearnRecord(wordId, confidence)
        console.log(`第${currentRound}遍学习记录提交成功:`, confidence)
    } catch (error) {
        console.error('提交学习记录失败（但不影响学习进度）:', error)
    }
    
    // 选择"认识"后，直接隐藏按钮并显示单词详情，不需要"继续"按钮
    hideOptions.value = true
    scheduleTask(() => {
        // 等待按钮隐藏动画完成后再显示单词详情，避免重叠
        showWordDetail.value = true
    }, 350) // 等待按钮隐藏动画完成（0.25s）+ 一点延迟（100ms）
}

async function loadWords() {
    try {
        // 不显示加载状态，直接加载，提升体验
        isLoading.value = false
        const words = await fetchLearnWords(10)
        wordList.value = Array.isArray(words) ? words : []
        if (wordList.value.length > 0) {
            loadCurrentWord()
        }
    } catch (error) {
        console.error('获取学习单词失败:', error)
        isLoading.value = false
    }
}

function loadCurrentWord() {
    // 只在切换单词时重置状态，不重置 learnProgress（因为这是不同单词的进度）
    const word = wordList.value[currentIndex.value]
    if (!word) return
    
    // 重置当前单词的状态（但不重置 learnProgress）
    clearTimers()
    selectedIndices.value = []
    hasAnswered.value = false
    
    // 根据当前单词的学习遍数决定是否显示选项框
    const wordId = word.wordId
    const completedRounds = learnProgress.value[wordId] || 0
    const currentRound = completedRounds + 1
    // 第一遍显示选项框，第二、三遍不显示
    // 如果学习进度为0（重新学习），也要显示选项框
    hideOptions.value = currentRound > 1 && completedRounds > 0
    
    showWordDetail.value = false
    showCorrectAnswer.value = false
    isViewAnswerMode.value = false
    hadWrongAttempt.value = false
    hadCorrectAnswer.value = false
    hadForgetAnswer.value = false
    hadKnowAnswer.value = false
    // 重置选项框显示标志，允许新单词显示进入动画
    optionsAlreadyShown.value = false
    
    // 立即隐藏圆圈，避免显示在错误位置
    isCirclePositionReady.value = false
    circleTopPosition.value = null
    
    // 等待DOM更新后再计算位置，使用多重等待确保 DOM 完全渲染和布局稳定
    // 只有第一遍学习时才需要计算选项位置
    if (currentRound === 1) {
        // 先等待 Vue 的 DOM 更新
        nextTick(() => {
            // 再等待浏览器完成布局
            requestAnimationFrame(() => {
                requestAnimationFrame(() => {
                    // 最后调用更新函数，函数内部还会再次检查
                    // 切换单词时需要强制隐藏，重新计算位置
                    updateOptionHeights(true)
                })
            })
        })
    }

    if (audio) {
        audio.pause()
        audio = null
    }
}

async function selectOption(index) {
    // 防止重复点击和无效点击
    if (isOptionDisabled(index)) return
    // 如果已经显示正确答案，允许继续点击其他选项查看英文单词
    // 只有在未显示正确答案且未点击正确选项时才阻止点击
    if (hasAnswered.value && !isViewAnswerMode.value && !hadCorrectAnswer.value && !showCorrectAnswer.value) return
    if (selectedIndices.value.includes(index)) return
    
    const correctIndex = correctOptionIndex.value
    const wordId = currentWord.value?.wordId
    
    // 添加选中的索引
    selectedIndices.value = [...selectedIndices.value, index]
    
    // 如果已经显示正确答案，点击其他选项只是为了查看英文单词
    // 不需要触发位置重新计算和其他逻辑，直接返回
    if (showCorrectAnswer.value && index !== correctIndex) {
        return
    }

    if (index === correctIndex) {
        // 答对了
        // 不设置 hasAnswered，允许继续点击其他选项
        showCorrectAnswer.value = true
        // 注意：不要在这里设置 optionsAlreadyShown，让每个新单词都能正常显示
        // optionsAlreadyShown.value = true

        // 更新学习进度（先更新，确保UI立即响应）
        if (wordId) {
            learnProgress.value[wordId] = 1
            console.log('第一遍学习完成（答对），wordId:', wordId, '当前进度:', learnProgress.value[wordId])
        }

        // 提交第一遍学习记录
        if (wordId) {
            try {
                await updateLearnRecord(wordId, 'know')
                console.log('第一遍学习记录提交成功: know')
            } catch (error) {
                console.error('提交学习记录失败（但不影响学习进度）:', error)
            }
        }

        // 如果不是查看答案模式，设置标记等待用户点击"继续"
        if (!hadWrongAttempt.value && !isViewAnswerMode.value) {
            hadCorrectAnswer.value = true
            // 确保选项框继续显示，等待用户点击"继续"
            hideOptions.value = false
        }
        
        // 点击正确选项后，不需要重新计算位置
        // 因为选项框内容没有变化（只是显示英文单词，高度是固定的）
        // 重新计算会导致位置跳跃，影响体验
    } else {
        // 答错了
        hadWrongAttempt.value = true
        // 如果已经点击了正确选项，不设置 hasAnswered，允许继续点击
        if (!hadCorrectAnswer.value) {
            hasAnswered.value = true
        }
        
        // 延迟显示正确答案和正确选项的英文单词，让用户先看到错误选项的英文
        // 增加延迟时间，让红色和绿色显示之间有更明显的间隔
        scheduleTask(() => {
            showCorrectAnswer.value = true
            // 确保正确选项也被添加到 selectedIndices，以便显示英文单词
            if (!selectedIndices.value.includes(correctIndex)) {
                selectedIndices.value = [...selectedIndices.value, correctIndex]
            }
            // 显示正确答案后，重新计算圆圈位置，确保对齐
            nextTick(() => {
                setTimeout(() => {
                    updateOptionHeights()
                }, 100) // 等待内容更新完成
            })
        }, 1200) // 改为1200毫秒延迟，让红色和绿色显示之间有更明显的间隔
    }
}

function isOptionDisabled(index) {
    if (hideOptions.value) return true
    if (selectedIndices.value.includes(index)) return true
    // 如果已经显示正确答案，允许继续点击其他选项查看英文单词
    // 只有在未显示正确答案且未点击正确选项时才禁用
    if (hasAnswered.value && !isViewAnswerMode.value && !hadCorrectAnswer.value && !showCorrectAnswer.value) return true
    return false
}

function isCorrectOption(index) {
    return index === correctOptionIndex.value
}

function isWrongOption(index) {
    return selectedIndices.value.includes(index) && index !== correctOptionIndex.value
}

function shouldShowWord(index) {
    // 如果是查看答案模式，只显示正确选项的单词
    if (isViewAnswerMode.value) {
        return index === correctOptionIndex.value
    }
    // 如果是正确选项，只有在 showCorrectAnswer 为 true 时才显示（延迟显示）
    if (index === correctOptionIndex.value) {
        return showCorrectAnswer.value
    }
    // 对于其他选项（错误选项），如果被选中就立即显示英文单词
    return selectedIndices.value.includes(index)
}

function getOptionWord(option, index) {
    // 直接使用后端返回的 word 字段
    if (option.word) {
        return option.word
    }
    // 如果没有，回退到当前学习的单词
    return currentWord.value?.word || ''
}

function optionClass(index) {
    return {
        correct: isCorrectOption(index) && (showCorrectAnswer.value || hasAnswered.value || hadCorrectAnswer.value),
        wrong: isWrongOption(index),
        disabled: isOptionDisabled(index),
        selected: selectedIndices.value.includes(index),
    }
}

function circleClass(index) {
    return {
        correct: isCorrectOption(index) && (showCorrectAnswer.value || hasAnswered.value || hadCorrectAnswer.value),
        wrong: isWrongOption(index),
        selected: selectedIndices.value.includes(index),
    }
}

async function viewAnswer() {
    if (hasSelectedAny.value || parsedOptions.value.length === 0) return
    const correctIndex = correctOptionIndex.value
    if (!selectedIndices.value.includes(correctIndex)) {
        selectedIndices.value = [...selectedIndices.value, correctIndex]
    }
    hasAnswered.value = true
    isViewAnswerMode.value = true
    showCorrectAnswer.value = true

    // 提交第一遍学习记录（看答案视为忘记）
    const wordId = currentWord.value?.wordId
    if (wordId) {
        // 先更新学习进度（即使 API 失败也要更新，保证 UI 正常）
        learnProgress.value[wordId] = 1
        console.log('第一遍学习完成（看答案），wordId:', wordId, '当前进度:', learnProgress.value[wordId])
        
        // 然后尝试提交到后端（失败不影响 UI）
        try {
            await updateLearnRecord(wordId, 'forget')
            console.log('第一遍学习记录提交成功: forget')
        } catch (error) {
            console.error('提交学习记录失败（但不影响学习进度）:', error)
        }
    }

    // 隐藏选项框和圆圈
    scheduleTask(() => {
        hideOptions.value = true
        showWordDetail.value = true
        // 不自动进入下一遍或下一个单词，等待用户点击"下一词"按钮
    }, 1200)
}

async function continueToDetail() {
    const wordId = currentWord.value?.wordId
    const currentRound = currentLearnRound.value
    
    // 防止重复点击
    if (showWordDetail.value) return
    
    // 立即隐藏圆圈，避免动画
    isCirclePositionReady.value = false
    
    // 第一遍学习：隐藏选项框（包括点击正确答案的情况）
    if (currentRound === 1 || hadCorrectAnswer.value) {
        // 如果答错了，提交第一遍学习记录（视为忘记）
        if (wordId && hadWrongAttempt.value && learnProgress.value[wordId] !== 1) {
            // 先更新学习进度（即使 API 失败也要更新，保证 UI 正常）
            learnProgress.value[wordId] = 1
            console.log('第一遍学习完成（答错），wordId:', wordId, '当前进度:', learnProgress.value[wordId])
            
            // 然后尝试提交到后端（失败不影响 UI）
            try {
                await updateLearnRecord(wordId, 'forget')
                console.log('第一遍学习记录提交成功: forget (答错)')
            } catch (error) {
                console.error('提交学习记录失败（但不影响学习进度）:', error)
            }
        }
        
        // 隐藏选项框
        hideOptions.value = true
        scheduleTask(() => {
            // 等待选项框完全隐藏后再显示单词详情，避免重叠
            showWordDetail.value = true
        }, 350) // 等待选项框隐藏动画完成（0.3s）+ 一点延迟（50ms）
    } else {
        // 第二、三遍学习：隐藏按钮
        hideOptions.value = true
        scheduleTask(() => {
            // 等待按钮隐藏动画完成后再显示单词详情，避免重叠
            showWordDetail.value = true
        }, 350) // 等待按钮隐藏动画完成（0.25s）+ 一点延迟（100ms）
    }
    
    // 标记已回答
    hasAnswered.value = true
    
    // 重置所有标记
    hadCorrectAnswer.value = false
    hadWrongAttempt.value = false
    hadForgetAnswer.value = false
    hadKnowAnswer.value = false
}

function nextWord() {
    // 防止重复点击
    if (!showWordDetail.value) return
    
    const wordId = currentWord.value?.wordId
    if (!wordId) return
    
    const completedRounds = learnProgress.value[wordId] || 0
    
    // 确保学习遍数不超过3遍
    if (completedRounds >= 3) {
        // 如果已完成3遍，进入下一个单词
        if (currentIndex.value < wordList.value.length - 1) {
            currentIndex.value += 1
            loadCurrentWord()
        } else {
            finishSession()
        }
        return
    }
    
    // 如果当前单词还没学完3遍，检查是否需要插入待复习的单词
    // 检查待复习队列，看是否有单词需要在当前遍后插入
    const shouldInsertReview = reviewQueue.value.find(item => {
        // 如果当前是第2遍（completedRounds === 1），且有待复习单词需要在第2遍后插入
        if (completedRounds === 1 && item.insertAfterRound === 2) {
            return true
        }
        // 如果当前是第3遍（completedRounds === 2），且有待复习单词需要在第3遍后插入
        if (completedRounds === 2 && item.insertAfterRound === 3) {
            return true
        }
        return false
    })
    
    if (shouldInsertReview) {
        // 插入待复习的单词到当前单词列表
        const reviewWordIndex = reviewQueue.value.findIndex(item => item.wordId === shouldInsertReview.wordId)
        const reviewWord = reviewQueue.value.splice(reviewWordIndex, 1)[0]
        
        // 检查待复习单词是否已经学习过3遍，如果是则跳过插入
        const reviewWordProgress = learnProgress.value[reviewWord.wordId] || 0
        if (reviewWordProgress >= 3) {
            console.warn('待复习单词已学习3遍，跳过插入，wordId:', reviewWord.wordId)
            // 继续执行后续逻辑，不插入单词
        } else {
            // 找到当前单词在列表中的位置，插入到下一个位置
            const currentWordIndex = wordList.value.findIndex(w => w.wordId === wordId)
            if (currentWordIndex !== -1) {
                // 检查待复习单词是否已经在列表中（避免重复插入）
                // 检查从当前索引之后的位置，避免重复插入
                const existsAfterCurrent = wordList.value.slice(currentWordIndex + 1).some(w => w.wordId === reviewWord.wordId)
                
                if (!existsAfterCurrent) {
                    // 找到待复习单词的完整数据
                    // 如果当前列表中找不到，说明这个单词可能已经被移除了
                    const reviewWordData = wordList.value.find(w => w.wordId === reviewWord.wordId)
                    
                    if (reviewWordData) {
                        // 创建新的对象副本，避免引用问题
                        const newWordData = { ...reviewWordData }
                        // 确保学习进度被重置为0（重新学习）
                        learnProgress.value[reviewWord.wordId] = 0
                        console.log('插入待复习单词:', newWordData.word, '到位置:', currentWordIndex + 1, '当前索引:', currentIndex.value, '学习进度已重置为0')
                        // 插入到当前单词的下一个位置
                        wordList.value.splice(currentWordIndex + 1, 0, newWordData)
                    } else {
                        console.warn('待复习单词数据未找到，wordId:', reviewWord.wordId, '可能已被移除，跳过插入')
                    }
                } else {
                    console.warn('待复习单词已在列表中（当前索引之后），跳过插入，wordId:', reviewWord.wordId, '当前索引:', currentIndex.value)
                }
            }
        }
    }
    
    // 重置状态，准备下一遍学习
    clearTimers()
    selectedIndices.value = []
    hasAnswered.value = false
    
    // 根据当前学习遍数决定是否显示选项框
    // 第一遍（completedRounds === 0）显示选项框，第二、三遍不显示
    const nextRound = completedRounds + 1
    
    // 确保不超过3遍
    if (nextRound > 3) {
        console.warn('学习遍数异常，已超过3遍，wordId:', wordId, 'completedRounds:', completedRounds)
        // 如果已完成3遍，进入下一个单词
        if (currentIndex.value < wordList.value.length - 1) {
            currentIndex.value += 1
            loadCurrentWord()
        } else {
            finishSession()
        }
        return
    }
    
    // 重置所有UI状态
    hideOptions.value = nextRound > 1
    showWordDetail.value = false
    showCorrectAnswer.value = false
    isViewAnswerMode.value = false
    
    // 重置所有标记
    hadWrongAttempt.value = false
    hadCorrectAnswer.value = false
    hadForgetAnswer.value = false
    hadKnowAnswer.value = false
    
    // 重置圆圈位置，准备下一遍学习
    isCirclePositionReady.value = false
    circleTopPosition.value = null
    
    console.log('进入第', nextRound, '遍学习，当前进度:', completedRounds, 'hideOptions:', hideOptions.value)
    
    // 如果是第一遍，需要重新计算选项位置
    if (nextRound === 1) {
        nextTick(() => {
            nextTick(() => {
                // 切换单词时需要强制隐藏，重新计算位置
                updateOptionHeights(true)
            })
        })
    }
}

function finishSession() {
    const sessionId = Date.now().toString()
    const sessionData = {
        mode: 'learn',
        wordList: wordList.value,
        wordIds: wordList.value.map(word => word.wordId),
        timestamp: Date.now(),
    }
    sessionStorage.setItem(`study_session_${sessionId}`, JSON.stringify(sessionData))

    const wordIdsParam = sessionData.wordIds.join(',')
    const isFirstGroup = Boolean(wordList.value[0]?.isFirstGroup)

    router.push({
        path: '/completion',
        query: {
            mode: 'learn',
            wordIds: wordIdsParam,
            isFirstGroup: isFirstGroup ? 'true' : 'false',
            sessionId,
        },
    })
}

function playAudio() {
    if (!currentWord.value?.audioUrl) return
    try {
        if (audio) {
            audio.pause()
        }
        const url = currentWord.value.audioUrl.startsWith('http')
            ? currentWord.value.audioUrl
            : `${window.location.origin}/${currentWord.value.audioUrl}`
        audio = new Audio(url)
        audio.play().catch((error) => {
            console.error('播放音频失败:', error)
        })
    } catch (error) {
        console.error('播放音频失败:', error)
    }
}

function backToHome() {
    router.push('/')
}

function noop() {}

function handleKeyPress(event) {
    if (showWordDetail.value || hideOptions.value) return
    const key = event.key
    const numeric = Number(key)
    if (!Number.isNaN(numeric) && numeric >= 1 && numeric <= 4) {
        const index = numeric - 1
        if (index < parsedOptions.value.length) {
            selectOption(index)
        }
    }
}

const optionHeights = ref({})
const circleTopPosition = ref(null) // 使用 null 作为初始值，表示未计算
const isCirclePositionReady = ref(false) // 标记位置是否已准备好

function updateOptionHeights() {
    // 先隐藏圆圈，避免显示在错误位置
    isCirclePositionReady.value = false
    
    // 使用 setTimeout 确保 DOM 完全渲染
    setTimeout(() => {
        const optionRows = document.querySelectorAll('.option-row')
        if (optionRows.length === 0) {
            console.log('没有找到选项行，重试...')
            // 如果没找到，再等一个 tick
            nextTick(() => {
                const retryRows = document.querySelectorAll('.option-row')
                if (retryRows.length > 0) {
                    calculateAndShowCircles(retryRows)
                }
            })
            return
        }
        
        calculateAndShowCircles(optionRows)
    }, 50)
}

function calculateAndShowCircles(optionRows) {
    // 记录每个选项行的实际高度和位置
    const rowData = []
    optionRows.forEach((row, index) => {
        const rect = row.getBoundingClientRect()
        optionHeights.value[index] = rect.height
        rowData.push({
            index,
            top: rect.top,
            height: rect.height,
            bottom: rect.top + rect.height
        })
    })
    
    // 获取第一个选项行的位置信息
    const firstOptionRow = optionRows[0]
    if (!firstOptionRow) {
        console.warn('未找到第一个选项行')
        return
    }
    
    // 获取第一个选项行的位置和尺寸
    const firstRowRect = firstOptionRow.getBoundingClientRect()
    const translateYOffset = 56 // 圆圈容器的 translateY(-56px) 偏移
    
    // 计算圆圈容器的 top 位置
    // 第一个圆圈的上顶端应该对齐第一个选项行的上边框
    // 第一个 circle-wrapper 的上边缘应该对齐第一个选项框的上边缘（firstRowRect.top）
    // 由于 circle-selectors 容器使用了 translateY(-56px)，容器的实际位置会向上移动 56px
    // 所以容器的 top 位置应该是：firstRowRect.top + translateYOffset
    // 这样容器的实际位置（考虑 translateY）就是：firstRowRect.top
    // 第一个 circle-wrapper 的上边缘就在：firstRowRect.top
    // 第一个圆圈的上顶端（在 circle-wrapper 中靠上对齐）就在：firstRowRect.top
    circleTopPosition.value = firstRowRect.top + translateYOffset
    
    // 位置设置完成后，显示圆圈
    isCirclePositionReady.value = true
    
    // 验证对齐情况 - 使用实际间距而不是假设的 gap
    const verification = rowData.map((r, i) => {
        if (i === 0) {
            return {
                index: r.index,
                optionTop: r.top,
                optionHeight: r.height,
                expectedCircleTop: firstRowRect.top,
                note: '第一个应该对齐'
            }
        } else {
            const prevRow = rowData[i - 1]
            // 计算实际间距：当前选项框的 top - 前一个选项框的 bottom
            const actualGap = r.top - prevRow.bottom
            // 预期位置：前一个的 top + 前一个的高度 + 实际间距
            const expectedTop = prevRow.top + prevRow.height + actualGap
            return {
                index: r.index,
                optionTop: r.top,
                optionHeight: r.height,
                prevBottom: prevRow.bottom,
                actualGap,
                expectedTop,
                diff: r.top - expectedTop,
                note: `实际间距: ${actualGap.toFixed(2)}px, 应该等于前一个的 top(${prevRow.top.toFixed(2)}) + height(${prevRow.height.toFixed(2)}) + gap(${actualGap.toFixed(2)}) = ${expectedTop.toFixed(2)}`
            }
        }
    })
    
    console.log('圆圈位置已设置:', {
        circleTopPosition: circleTopPosition.value,
        firstRowTop: firstRowRect.top,
        firstRowHeight: firstRowRect.height,
        translateYOffset,
        optionCount: optionRows.length,
        rowData: rowData.map(r => ({ 
            index: r.index, 
            top: r.top.toFixed(2), 
            height: r.height.toFixed(2),
            bottom: r.bottom.toFixed(2)
        })),
        verification
    })
    
    // 检查是否有高度不一致的问题
    const heights = rowData.map(r => r.height)
    const minHeight = Math.min(...heights)
    const maxHeight = Math.max(...heights)
    if (Math.abs(maxHeight - minHeight) > 0.1) {
        console.warn('⚠️ 选项框高度不一致:', {
            minHeight: minHeight.toFixed(2),
            maxHeight: maxHeight.toFixed(2),
            diff: (maxHeight - minHeight).toFixed(2),
            heights: heights.map(h => h.toFixed(2))
        })
    }
    
    // 检查间距是否一致
    const gaps = []
    for (let i = 1; i < rowData.length; i++) {
        const gap = rowData[i].top - rowData[i - 1].bottom
        gaps.push(gap)
    }
    if (gaps.length > 0) {
        const minGap = Math.min(...gaps)
        const maxGap = Math.max(...gaps)
        if (Math.abs(maxGap - minGap) > 0.1) {
            console.warn('⚠️ 选项框间距不一致:', {
                minGap: minGap.toFixed(2),
                maxGap: maxGap.toFixed(2),
                diff: (maxGap - minGap).toFixed(2),
                gaps: gaps.map(g => g.toFixed(2))
            })
        }
    }
}

function getOptionHeight(index) {
    return optionHeights.value[index] || 42
}

onMounted(() => {
    // 记录学习开始时间
    studyStartTime = Date.now()
    console.log('学习开始，开始时间:', new Date(studyStartTime).toLocaleString())
    
    loadWords()
    window.addEventListener('keydown', handleKeyPress)
    window.addEventListener('resize', updateOptionHeights)
    window.addEventListener('scroll', updateOptionHeights)
})

onBeforeUnmount(async () => {
    clearTimers()
    window.removeEventListener('keydown', handleKeyPress)
    window.removeEventListener('resize', updateOptionHeights)
    window.removeEventListener('scroll', updateOptionHeights)
    if (audio) {
        audio.pause()
        audio = null
    }
    
    // 计算学习时长并保存
    if (studyStartTime) {
        const endTime = Date.now()
        const duration = Math.floor((endTime - studyStartTime) / 1000 / 60) // 转换为分钟
        console.log('学习结束，时长:', duration, '分钟')
        
        if (duration > 0) {
            try {
                await saveStudySession(duration)
                console.log('学习时长保存成功')
            } catch (error) {
                console.error('保存学习时长失败:', error)
                // 保存失败不影响页面退出，静默处理
            }
        }
        studyStartTime = null
    }
})
</script>

<style scoped>
.dashed-border-top,
.dashed-border-bottom,
.dashed-divider {
    display: none;
}

.study-screen {
    position: fixed;
    inset: 0;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    color: #f8fafc;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    overflow: visible;
    overflow-x: visible;
}

.blur-overlay {
    position: absolute;
    inset: 0;
    backdrop-filter: blur(35px) brightness(0.92);
    -webkit-backdrop-filter: blur(35px) brightness(0.92);
    background: rgba(15, 23, 42, 0.35);
    z-index: 0;
}

.topbar {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32px 56px 20px;
    gap: 24px;
}

.topbar-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.progress-label {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: rgba(226, 232, 240, 0.85);
}

.top-actions {
    display: flex;
    align-items: center;
    gap: 16px;
}

.icon-btn {
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
    color: rgba(226, 232, 240, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.2s ease;
}

.icon-btn:hover {
    opacity: 0.7;
}

.icon-btn svg {
    display: block;
}

.study-body {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 0;
    padding: 20px 0 40px 0;
    overflow: visible;
}

.study-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    text-align: left;
    flex: 1;
    max-width: 830px;
    margin: 0 auto;
    padding-top: 0;
}

.word-display {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
}

.word-section-wrapper {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.word-section {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    margin-bottom: 0;
    margin-left: 0;
    margin-top: 0;
}

.word-header {
    width: 100%;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
    margin-bottom: 16px;
}

.word-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.learn-progress-circles {
    display: flex;
    flex-direction: column-reverse;
    gap: 6px;
    align-items: center;
    flex-shrink: 0;
    margin-top: 0;
    padding-left: 16px;
}

.progress-circle {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(226, 232, 240, 0.3);
    border: none;
    transition: all 0.3s ease;
}

.progress-circle.active {
    background: #14b8a6;
    border: none;
    box-shadow: none;
}

.learn-round-label {
    color: rgba(226, 232, 240, 0.8);
    font-size: 14px;
    margin-top: 8px;
    font-weight: 500;
}

/* 复习模式按钮样式（参考 ReviewPage） */
.choices {
    position: fixed;
    bottom: 38px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: space-around;
    align-items: center;
    z-index: 2;
}

.btn {
    appearance: none;
    border: none;
    background: transparent;
    font-size: 18px;
    font-weight: 500;
    color: #ffffff;
    position: relative;
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    transform-origin: center;
}

.btn:active {
    transform: scale(0.92);
    opacity: 0.7;
}

.btn:hover {
    opacity: 0.9;
}

.btn::after {
    content: "";
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: -8px;
    width: 18px;
    height: 3px;
    border-radius: 2px;
    opacity: .85;
}

.btn.know::after {
    background: #14b8a6;
}

.btn.forget::after {
    background: #ef4444;
}

/* 按钮过渡动画 - 使用优雅的淡入淡出和轻微缩放效果 */
.fade-choices-enter-active {
    transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.fade-choices-leave-active {
    transition: all 0.25s cubic-bezier(0.55, 0.06, 0.68, 0.19);
}

.fade-choices-enter-from {
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    filter: blur(4px);
}

.fade-choices-leave-to {
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
    filter: blur(2px);
}

.word-text {
    font-size: 36px;
    font-weight: 700;
    letter-spacing: 0.02em;
    margin: 0;
    line-height: 1.2;
    text-shadow: 0 18px 38px rgba(15, 23, 42, 0.35);
}

.word-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}

.chip {
    border: none;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    color: #f8fafc;
    padding: 4px 12px;
    cursor: pointer;
    font-size: 12px;
    transition: all 0.25s ease;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.chip:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.28);
}

.chip:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.phonetic {
    font-size: 13px;
    color: rgba(226, 232, 240, 0.75);
}

.word-hint {
    font-size: 12px;
    letter-spacing: 0.15em;
    color: rgba(226, 232, 240, 0.6);
    margin: 10px 0 0;
}

.word-meanings-inline {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 12px;
    width: 100%;
}

.meaning-item-inline {
    display: flex;
    gap: 10px;
    align-items: baseline;
    color: rgba(226, 232, 240, 0.95);
}

.part-of-speech-inline {
    font-weight: 600;
    min-width: 38px;
    color: rgba(248, 250, 252, 0.75);
    font-size: 14px;
}

.meaning-text-inline {
    line-height: 1.6;
    font-size: 15px;
    flex: 1;
}

.example-box-inline {
    display: flex;
    gap: 16px;
    margin-top: 20px;
    padding: 18px 20px;
    border-radius: 20px;
    background: rgba(15, 23, 42, 0.45);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 32px 65px rgba(15, 23, 42, 0.45);
    align-items: flex-start;
}

.example-icon-inline {
    font-size: 22px;
    flex-shrink: 0;
    margin-top: 2px;
}

.example-content-inline {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}

.example-en-inline {
    font-size: 15px;
    line-height: 1.6;
    color: rgba(226, 232, 240, 0.95);
    font-weight: 500;
}

.example-cn-inline {
    font-size: 14px;
    line-height: 1.6;
    color: rgba(226, 232, 240, 0.75);
}

.options-container {
    --option-height: 70px;
    --circle-size: 68px;
    --option-gap: 10px;
    position: relative;
    width: 100%;
    margin-top: 8px;
    padding: 0;
    margin-left: 0; /* 确保左对齐 */
    margin-right: 0;
}

.options-wrapper {
    display: flex;
    align-items: flex-start;
    justify-content: flex-start; /* 改为左对齐，与单词对齐 */
    width: 100%;
    padding: 0;
    position: relative;
}

.circle-selectors {
    position: fixed;
    z-index: 1000 !important;
    display: flex !important;
    flex-direction: column;
    gap: var(--option-gap, 10px); /* 确保与 .options-list 的 gap 一致 */
    align-items: center;
    margin: 0;
    padding: 0;
    width: auto !important;
    height: auto !important;
    /* 完全禁用过渡，避免任何动画 */
    transition: none !important;
    opacity: 1 !important;
    visibility: visible !important;
    /* 直接定义 CSS 变量，确保圆圈大小正确 */
    --circle-size: 68px;
    --option-gap: 10px;
    /* transform 在 .left 和 .right 中单独定义 */
}

.circle-selectors.left::before {
    content: '';
    position: absolute;
    top: calc(var(--circle-size) / -2 + 4px);
    right: calc(var(--circle-size) / -2 + 4px);
    bottom: calc(var(--circle-size) / -2 + 4px);
    left: calc(var(--circle-size) / -2 + 4px);
    border: 1px dashed rgba(226, 232, 240, 0.4);
    border-left: none;
    border-radius: 0 20px 20px 0;
    pointer-events: none;
}

.circle-selectors.right::before {
    content: '';
    position: absolute;
    top: calc(var(--circle-size) / -2 + 4px);
    right: calc(var(--circle-size) / -2 + 4px);
    bottom: calc(var(--circle-size) / -2 + 4px);
    left: calc(var(--circle-size) / -2 + 4px);
    border: 1px dashed rgba(226, 232, 240, 0.4);
    border-right: none;
    border-radius: 20px 0 0 20px;
    pointer-events: none;
}

.circle-selectors.left {
    left: 0 !important;
    transform: translateY(-56px) !important;
    padding-left: 0 !important;
    margin-left: 0 !important;
}

.circle-selectors.right {
    right: 0 !important;
    transform: translateY(-56px) !important;
    padding-right: 0 !important;
    margin-right: 0 !important;
}

.circle-wrapper {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    cursor: pointer;
    position: relative;
    width: var(--circle-size);
    min-width: var(--circle-size);
    flex-shrink: 0;
    padding: 0;
    margin: 0;
}

.circle-selectors.left .circle-wrapper {
    margin-left: 0;
    display: flex;
    align-items: flex-start;
    justify-content: center;
}

.circle-selectors.right .circle-wrapper {
    margin-right: 0;
    display: flex;
    align-items: flex-start;
    justify-content: center;
}

.options-container {
    overflow: visible;
}

.study-screen {
    overflow-x: visible;
}

.circle-selectors .circle-selector {
    width: 68px !important;
    height: 68px !important;
    min-width: 68px !important;
    min-height: 68px !important;
    border-radius: 50%;
    border: 2px solid rgba(226, 232, 240, 0.6) !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    background: rgba(15, 23, 42, 0.8) !important;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition: none !important; /* 移除动画 */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);
    box-sizing: border-box;
    flex-shrink: 0;
    opacity: 1 !important;
    visibility: visible !important;
}

.circle-selectors .circle-selector.correct {
    border-color: rgba(34, 197, 94, 0.9);
    background: rgba(34, 197, 94, 0.2);
    color: #ecfdf5;
}

.circle-selectors .circle-selector.wrong {
    border-color: rgba(248, 113, 113, 0.9);
    background: rgba(248, 113, 113, 0.2);
    color: #fef2f2;
}

.circle-selectors .circle-selector svg {
    width: 26px;
    height: 26px;
}

.circle-selectors .circle-selector span {
    font-weight: 600;
}

.circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    min-width: 100%;
    min-height: 100%;
    border-radius: 50%;
    background: rgba(30, 41, 59, 0.75);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: #f8fafc;
    font-weight: 600;
    font-size: 16px;
    transition: transform 0.25s ease;
    box-sizing: border-box;
    flex-shrink: 0;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}

.circle-selectors .circle-selector.correct .circle {
    background: rgba(34, 197, 94, 0.85);
    color: #022c22;
    animation: none !important; /* 移除动画 */
}

.circle-selectors .circle-selector.wrong .circle {
    background: rgba(248, 113, 113, 0.9);
    color: #7f1d1d;
    animation: none !important; /* 移除动画 */
}

.circle-selectors .circle-selector.selected:not(.correct):not(.wrong) {
    border-color: rgba(34, 197, 94, 0.5);
    background: rgba(34, 197, 94, 0.12);
}

.options-list {
    width: 830px;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0; /* 改为左对齐，与单词对齐 */
    position: relative;
    z-index: 1;
    padding: 0; /* 移除左右 padding，与单词对齐 */
    box-sizing: border-box;
}

.option-row {
    display: flex;
    align-items: center;
    margin: 0;
    padding: 0;
    /* 固定高度，避免跳动，使用实际高度而不是固定值 */
    min-height: var(--option-height, 70px);
    height: var(--option-height, 70px);
    /* 确保选项框之间有间隔 */
    margin-bottom: 0;
    box-sizing: border-box;
}

.option-item {
    position: relative;
    width: 100%;
    min-height: var(--option-height);
    height: var(--option-height);
    padding: 8px 18px;
    border-radius: 16px;
    display: flex;
    align-items: center;
    background: rgba(15, 23, 42, 0.32);
    border: 2px solid rgba(255, 255, 255, 0.08);
    box-shadow: 0 24px 45px rgba(15, 23, 42, 0.45);
    cursor: pointer;
    /* 只对颜色变化和 hover 效果添加动画，保持平滑过渡 */
    transition: transform 0.2s ease, background 0.3s ease, border-color 0.3s ease, box-shadow 0.2s ease;
    /* 固定高度，避免内容变化导致跳动 */
    box-sizing: border-box;
    overflow: hidden;
}

.no-transition .option-item {
    transition: none !important;
}

.no-transition .option-item * {
    transition: none !important;
}

.option-item:hover {
    transform: translateY(-2px); /* 和主页 study 模块一样的 hover 效果 */
    background: rgba(30, 41, 59, 0.4);
    box-shadow: 0 28px 55px rgba(15, 23, 42, 0.55);
}

.option-item.disabled {
    cursor: default;
    opacity: 0.85;
}

.option-item.correct {
    background: rgba(34, 197, 94, 0.26);
    border-color: rgba(34, 197, 94, 0.55);
}

.option-item.wrong {
    background: rgba(248, 113, 113, 0.22);
    border-color: rgba(248, 113, 113, 0.45);
}

.option-item.selected:not(.correct):not(.wrong) {
    border-color: rgba(34, 197, 94, 0.45);
}

.selected-line {
    display: none;
    left: 0;
    right: 0;
    height: 3px;
    background: rgba(34, 197, 94, 0.85);
    border-radius: 2px;
    box-shadow: 0 0 12px rgba(34, 197, 94, 0.45);
    animation: slideIn 0.4s ease forwards;
}

.option-content {
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* 确保内容不会导致选项框高度变化 */
    flex: 1;
    min-height: 0;
}

.option-header {
    display: flex;
    align-items: baseline;
    gap: 12px;
}

.option-label {
    font-size: 15px;
    font-weight: 600;
    color: rgba(226, 232, 240, 0.9);
}

.option-word {
    font-size: 16px;
    font-weight: 600;
    color: rgba(250, 250, 250, 0.95);
    letter-spacing: 0.02em;
}

.option-text {
    font-size: 16px;
    line-height: 1.6;
    color: rgba(226, 232, 240, 0.95);
}

.action-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 20px;
    margin-bottom: 40px;
    padding-bottom: 20px;
}

.action-btn {
    min-width: 120px;
    padding: 12px 24px;
    border-radius: 999px;
    border: none;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.action-btn.primary {
    background: linear-gradient(135deg, #22c55e, #0ea5e9);
    color: #0f172a;
    box-shadow: 0 18px 35px rgba(14, 165, 233, 0.35);
}

.action-btn.primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 20px 40px rgba(14, 165, 233, 0.42);
}

.action-btn.ghost {
    background: rgba(15, 23, 42, 0.55);
    color: #e2e8f0;
    border: 1px solid rgba(226, 232, 240, 0.25);
}

.action-btn.ghost:hover {
    transform: translateY(-2px);
    box-shadow: 0 16px 32px rgba(15, 23, 42, 0.4);
}

.action-btn.next-word-btn {
    background: transparent;
    color: #ffffff;
    border: none;
    padding: 12px 24px;
    min-width: 120px;
    font-size: 16px;
    font-weight: 500;
    position: relative;
    box-shadow: none;
    display: flex;
    align-items: center;
    justify-content: center;
}

.action-btn.next-word-btn:hover {
    transform: none;
    box-shadow: none;
}

.action-btn.next-word-btn::after {
    content: '';
    position: absolute;
    bottom: -4px;
    left: 0;
    right: 0;
    height: 2px;
    background: #34d399;
    border-radius: 1px;
}

.word-detail-section {
    width: 100%;
    max-width: 640px;
    margin: 36px auto 0;
    padding: 28px 32px;
    border-radius: 24px;
    background: rgba(15, 23, 42, 0.45);
    box-shadow: 0 32px 65px rgba(15, 23, 42, 0.45);
    display: flex;
    flex-direction: column;
    gap: 24px;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}

.word-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.detail-word {
    font-size: 34px;
    font-weight: 700;
}

.detail-meta {
    display: flex;
    align-items: center;
    gap: 12px;
}

.detail-phonetic {
    font-size: 15px;
    color: rgba(226, 232, 240, 0.8);
}

.detail-audio {
    border: none;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 999px;
    padding: 6px;
    color: #f8fafc;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.word-meanings-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.meaning-item {
    display: flex;
    gap: 12px;
    align-items: baseline;
    color: rgba(226, 232, 240, 0.95);
}

.meaning-item .part-of-speech {
    font-weight: 600;
    min-width: 42px;
    color: rgba(248, 250, 252, 0.75);
}

.meaning-item .meaning-text {
    line-height: 1.7;
}

.derivative-words {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.derivative-title {
    font-weight: 600;
    color: rgba(226, 232, 240, 0.8);
}

.derivative-list {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.derivative-item {
    padding: 6px 12px;
    border-radius: 999px;
    background: rgba(59, 130, 246, 0.18);
    color: rgba(226, 232, 240, 0.95);
    font-size: 13px;
}

.example-box {
    display: flex;
    gap: 16px;
    padding: 18px 20px;
    border-radius: 20px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(15, 23, 42, 0.95);
}

.example-icon {
    font-size: 22px;
}

.example-content {
    display: flex;
    flex-direction: column;
    gap: 10px;
    color: #0f172a;
}

.example-en {
    font-weight: 600;
}

.example-cn {
    color: rgba(15, 23, 42, 0.7);
}

.fade-options-enter-active {
    transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.fade-options-leave-active {
    transition: all 0.3s cubic-bezier(0.55, 0.06, 0.68, 0.19);
}

.fade-options-enter-from {
    opacity: 0;
    transform: translateY(20px) scale(0.92);
    filter: blur(6px);
}

.fade-options-leave-to {
    opacity: 0;
    transform: translateY(-10px) scale(0.96);
    filter: blur(3px);
}

.fade-word-enter-active {
    transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.fade-word-leave-active {
    transition: all 0.2s cubic-bezier(0.55, 0.06, 0.68, 0.19);
}

.fade-word-enter-from {
    opacity: 0;
    transform: translateY(-4px) scale(0.95);
}

.fade-word-leave-to {
    opacity: 0;
    transform: translateY(2px) scale(0.98);
}

.detail-fade-enter-active {
    transition: all 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.detail-fade-leave-active {
    transition: all 0.3s cubic-bezier(0.55, 0.06, 0.68, 0.19);
}

.detail-fade-enter-from {
    opacity: 0;
    transform: translateY(12px) scale(0.94);
    filter: blur(4px);
}

.detail-fade-leave-to {
    opacity: 0;
    transform: translateY(-6px) scale(0.97);
    filter: blur(2px);
}

@keyframes scaleIn {
    0% {
        transform: scale(0.85);
        opacity: 0.5;
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes scaleInWrong {
    0% {
        transform: scale(0.85);
        opacity: 0.5;
    }
    50% {
        transform: scale(1.05);
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@media (max-width: 1280px) {
    .study-body {
        gap: 48px;
        padding: 20px 48px 80px;
    }

    .study-content {
        margin-left: 0;
        align-items: center;
        text-align: center;
    }

    .word-section {
        align-items: center;
    }

    .word-hint {
        text-align: center;
    }

    .options-wrapper {
        gap: 24px;
    }

    .circle-selectors.left,
    .circle-selectors.right {
        margin: 0;
    }
}

@media (max-width: 1024px) {
    .study-body {
        flex-direction: column;
        gap: 40px;
        padding: 24px 24px 80px;
    }

    .study-content {
        align-items: center;
        text-align: center;
    }

    .word-section {
        align-items: center;
    }

    .options-wrapper {
        flex-direction: column;
        gap: 24px;
    }

    .word-text {
        font-size: 48px;
    }

    .circle-selectors {
        width: auto !important;
        height: auto !important;
    }

    .options-list {
        width: 100%;
    }
}

@media (max-width: 640px) {
    .topbar {
        padding: 24px 20px 16px;
    }

    .word-text {
        font-size: 40px;
    }

    .options-wrapper {
        gap: 14px;
    }

    .word-detail-section {
        padding: 24px 20px;
    }
}
</style>